package com.nbcio.iot.protocol.udp;

import com.nbcio.iot.config.IotServerProperties;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramChannel;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.util.CharsetUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import java.net.InetSocketAddress;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiConsumer;

/**
 * UDP服务器管理器
 * 支持接收UDP数据包并转发到数据处理流程
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class UdpServerManager {

    private final AtomicBoolean running = new AtomicBoolean(false);
    private EventLoopGroup group;
    private Channel serverChannel;
    private BiConsumer<String, String> messageListener;
    private int serverPort = 9998; // 默认端口
    private int bufferSize = 1024; // 可通过配置覆盖

    private final IotServerProperties serverProperties;

    public void setMessageListener(BiConsumer<String, String> listener) {
        this.messageListener = listener;
    }

    public void setServerPort(int port) {
        this.serverPort = port;
    }

    @PostConstruct
    public void start() {
        // 读取配置
        if (serverProperties != null && serverProperties.getUdpServer() != null) {
            this.serverPort = serverProperties.getUdpServer().getPort();
            this.bufferSize = serverProperties.getUdpServer().getBufferSize();
            boolean enabled = serverProperties.getUdpServer().isEnabled();
            if (!enabled) {
                log.info("[UDP-SERVER] 配置为关闭，跳过启动 (port={})", serverPort);
                return;
            }
        }

        if (running.compareAndSet(false, true)) {
            group = new NioEventLoopGroup(1);
            try {
                Bootstrap b = new Bootstrap();
                b.group(group)
                 .channel(NioDatagramChannel.class)
                 .option(ChannelOption.SO_BROADCAST, false)
                 .option(ChannelOption.SO_RCVBUF, bufferSize)
                 .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
                 .handler(new SimpleChannelInboundHandler<DatagramPacket>() {
                     @Override
                     protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet) {
                         InetSocketAddress sender = packet.sender();
                         String clientId = sender.getAddress().getHostAddress() + ":" + sender.getPort();
                         String data = packet.content().toString(CharsetUtil.UTF_8);
                         log.info("[UDP-SERVER] 收到客户端 {} 数据: {}", clientId, data);
                         if (messageListener != null) {
                             messageListener.accept("udp/" + clientId, data);
                         }
                     }
                     @Override
                     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
                         log.warn("[UDP-SERVER] 通道异常: {}", cause.getMessage());
                     }
                 });
                ChannelFuture f = b.bind(serverPort).sync();
                serverChannel = f.channel();
                log.info("[UDP-SERVER] UDP服务器(Netty)启动，监听端口: {}", serverPort);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                log.error("[UDP-SERVER] 启动中断", e);
                running.set(false);
                if (group != null) group.shutdownGracefully();
            } catch (Exception e) {
                log.error("[UDP-SERVER] 启动失败，端口: {}", serverPort, e);
                running.set(false);
                if (group != null) group.shutdownGracefully();
            }
        }
    }

    @PreDestroy
    public void stop() {
        if (running.compareAndSet(true, false)) {
            log.info("[UDP-SERVER] 正在停止UDP服务器...");
            try {
                if (serverChannel != null) {
                    serverChannel.close().syncUninterruptibly();
                }
            } finally {
                if (group != null) group.shutdownGracefully();
            }
            log.info("[UDP-SERVER] UDP服务器已停止");
        }
    }

    /**
     * 向指定客户端发送UDP数据包
     */
    public boolean sendToClient(String clientAddress, int clientPort, String message) {
        if (serverChannel == null || !serverChannel.isActive()) {
            return false;
        }
        io.netty.channel.socket.DatagramPacket pkt = new io.netty.channel.socket.DatagramPacket(
                io.netty.buffer.Unpooled.copiedBuffer(message, CharsetUtil.UTF_8),
                new InetSocketAddress(clientAddress, clientPort)
        );
        serverChannel.writeAndFlush(pkt);
        log.info("[UDP-SERVER] 向客户端 {}:{} 发送数据: {}", clientAddress, clientPort, message);
        return true;
    }

    /**
     * 检查UDP服务器是否运行中
     */
    public boolean isRunning() {
        return running.get() && serverChannel != null && serverChannel.isActive();
    }

    /**
     * 获取服务器端口
     */
    public int getServerPort() {
        return serverPort;
    }
}

